package br.com.ebc.icontatos.boundary;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.faces.component.html.HtmlDataTable;
import javax.faces.convert.Converter;
import javax.faces.model.SelectItem;
import javax.persistence.NoResultException;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import br.com.ebc.icontatos.converter.CidadeConverter;
import br.com.ebc.icontatos.converter.EmissoraConverter;
import br.com.ebc.icontatos.converter.EstadoConverter;
import br.com.ebc.icontatos.converter.PaisConverter;
import br.com.ebc.icontatos.model.Cidade;
import br.com.ebc.icontatos.model.Contato;
import br.com.ebc.icontatos.model.Emissora;
import br.com.ebc.icontatos.model.Estado;
import br.com.ebc.icontatos.model.Evento;
import br.com.ebc.icontatos.model.FiltroGrupo;
import br.com.ebc.icontatos.model.GrupoEnvio;
import br.com.ebc.icontatos.model.Interesse;
import br.com.ebc.icontatos.model.Pais;
import br.com.ebc.icontatos.model.Serie;
import br.com.ebc.icontatos.model.Usuario;
import br.com.ebc.icontatos.repository.CidadeRepository;
import br.com.ebc.icontatos.repository.EmissoraRepository;
import br.com.ebc.icontatos.repository.EstadoRepository;
import br.com.ebc.icontatos.repository.FiltroGrupoRepository;
import br.com.ebc.icontatos.repository.GrupoEnvioRepository;
import br.com.ebc.icontatos.repository.InteresseRepository;
import br.com.ebc.icontatos.repository.PaisRepository;
import br.com.ebc.icontatos.repository.UsuarioRepository;

@Controller("grupoEnvioManagedbean")
@Scope("session")
public class GrupoEnvioManagedbean extends AbstractFormManagedbean{

	@Resource
	private GrupoEnvioRepository grupoEnvioDAO;
	@Resource
	private FiltroGrupoRepository filtroGrupoDAO;
	@Resource
	private PaisRepository paisDAO;
	@Resource
	private EstadoRepository estadoDAO;
	@Resource
	private CidadeRepository cidadeDAO;
	@Resource
	private EmissoraRepository emissoraDAO;
	@Resource
	private InteresseRepository interesseDAO;
	@Resource 
	private UsuarioRepository usuarioDAO;
	private GrupoEnvio grupoEnvio = new GrupoEnvio();
	private GrupoEnvio visualizar = new GrupoEnvio();
	private FiltroGrupo filtroGrupo = new FiltroGrupo();
	private HtmlDataTable grupoEnvioHDT = new HtmlDataTable();
	private List<GrupoEnvio> grupos = new ArrayList<GrupoEnvio>();
	private Emissora emissora = new Emissora();
	private Serie serie = new Serie();
	private Interesse interesse = new Interesse();
	private Pais pais = new Pais();
	private Estado estado = new Estado();
	private Cidade cidade = new Cidade();
	private List<SelectItem> objetosEstados = new ArrayList<SelectItem>();
	private List<SelectItem> objetosCidades = new ArrayList<SelectItem>();
	private String pesquisado;
	private Contato contato = new Contato();
	private Usuario usuario = new Usuario();
	private HtmlDataTable usuarioHDT = new HtmlDataTable();
	private List<Usuario> usuarios = new ArrayList<Usuario>();
	private boolean todos;
	private Emissora visualizarEmissora = new Emissora();
	private Serie visualizarSerie = new Serie();
	private Interesse visualizarInteresse = new Interesse();
	private Pais visualizarPais = new Pais();
	private Estado visualizarEstado = new Estado();
	private Cidade visualizarCidade = new Cidade();
	private FiltroGrupo visualizarFiltro = new FiltroGrupo();
	
	public GrupoEnvioManagedbean() { // TODO ver o problema do total de usuarios
		super();
		try{
			iniciarEstados();
			iniciarCidades();
		} catch (NullPointerException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * metodo que limpa e cria uma nova lista de estados
	 */
	private void iniciarEstados() {
		getObjetosEstados().clear();
		getObjetosEstados().add(new SelectItem(null, "-- Selecione --"));
	}
	
	/**
	 * metodo que limpa e cria uma nova lista de cidades
	 */
	private void iniciarCidades(){
		getObjetosCidades().clear();
		getObjetosCidades().add(new SelectItem(null, "-- Selecione --"));
	}
	
	/**
	 * @return
	 * metodo que traz todos os grupos 
	 */
	@SuppressWarnings("unchecked")
	@PostConstruct
	public List<GrupoEnvio> listarGrupos(){
		grupos = grupoEnvioDAO.todos();
		return grupos;
	}
	
	/**
	 * @return
	 * metodo para salvar o grupo de envio
	 * percorremos uma lista de usuarios
	 * vemos se o objeto selecionado esta como true
	 * adiciono o usuario na lista 
	 * salvo o grupo de envio
	 */
	public String cadastrarGrupoEnvio(){
		for (Usuario obj : usuarios) {
			if (obj.isSelecionado()) {
				getGrupoEnvio().getUsuarios().add(obj);
			}
		}
		getFiltroGrupo().setDescricaoFiltroGrupo(criaFiltro());
		getGrupoEnvio().setFiltroGrupo(getFiltroGrupo());
		getGrupoEnvio().setTotalUsuarios(getGrupoEnvio().getUsuarios().size());
		grupoEnvioDAO.salvar(getGrupoEnvio());
		limpar();
		listarGrupos();
		usuarios.clear();
		return "sucesso";
	}

	/**
	 * metodo que limpa os campos no cadastro do grupo de envio
	 */
	public void limpar() {
		grupoEnvio = new GrupoEnvio();
		filtroGrupo = new FiltroGrupo();
		emissora = new Emissora();
		interesse = new Interesse();
		serie = new Serie();
		pais = new Pais();
		estado = new Estado();
		cidade = new Cidade();
		setPesquisado(null);
		setTodos(false);
	}

	/**
	 * @return
	 * metodo que cria uma string com as escolhas feitas para o grupo de envio
	 */
	public String criaFiltro() {
		StringBuffer sb = new StringBuffer();
		try{
			sb.append(emissora.getDescricaoEmissora());
			
			if(!serie.getDescricaoSerie().equals("")){
				sb.append(" - ");
				sb.append(serie.getDescricaoSerie()); 
			}
			
			if(interesse != null){
				sb.append(" - ");
				sb.append(interesse.getDescricaoInteresse());
			}
			
			if(!pais.getNomePais().equals("")){
				sb.append(" - ");
				sb.append(pais.getNomePais());
			}
	
			if(!estado.getNomeEstado().equals("")){
				sb.append(" - ");
				sb.append(estado.getNomeEstado());
			}
	
			if(!cidade.getNomeCidade().equals("")){
				sb.append(" - ");
				sb.append(cidade.getNomeCidade());
			}
			
		} catch (NullPointerException e) {
			e.printStackTrace();
		}	
		return sb.toString();
	}
	
	/**
	 * @return
	 * metodo que redireciona para uma pagina 
	 */
	public String redirect(){
		return "novo";
	}
	
	/**
	 * @return
	 * metodo para voltar para uma pagina
	 */
	public String voltar(){
		getUsuarios().clear();
		limpar();
		return "voltar";
	}
	
	/**
	 * @return
	 * metodo para excluir o grupo envio selecionado
	 */
	public String excluirGrupoEnvio(){
		grupoEnvioDAO.excluir((GrupoEnvio) getGrupoEnvioHDT().getRowData());
		listarGrupos();
		return null;
	}
	
	/**
	 * metodo para visualizar o grupo de envio selecionado
	 */
	public void visualizarGrupoEnvio(){
		setVisualizar((GrupoEnvio) getGrupoEnvioHDT().getRowData());
		if(getVisualizar().getFiltroGrupo() != null)
			setVisualizarFiltro(filtroGrupoDAO.find(getVisualizar().getFiltroGrupo().getIdFiltroGrupo()));
	}
	
	/**
	 * metodo que vai selecionar ou nao todos os objetos da lista
	 * verifico se o objeto esta como true
	 * caso sim percorro a lista de usuarios e seto todos como true
	 * caso contrario seto como false
	 */
	public void selecionarTodos(){
		if(isTodos()){
			for(Usuario obj : usuarios){
				obj.setSelecionado(true);
			}
		} else {
			for(Usuario obj : usuarios){
				obj.setSelecionado(false);
			}
		}
	}
	
	/**
	 * @return
	 * @throws NoResultException
	 * @throws SQLException
	 * metodo que pesquisa os contatos por nome ou email
	 */
	public List<Usuario> buscaUsuarios(){
		try{
			if(!getCidade().getNomeCidade().equals("")){
				setCidade(cidadeDAO.findCidade(getCidade().getNomeCidade()));
			}
			usuarios = usuarioDAO.findUsuarios(getPesquisado(), getEmissora(), getSerie(), getInteresse(), getPais(), getEstado(), getCidade());
		} catch (NoResultException e) {
			e.printStackTrace();
		} catch (NullPointerException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}	 
		return usuarios;
	}
	
	/**
	 * @return
	 * metodo que preenche a combo de pais
	 * crio uma lista de paises que recebe todo os paises 
	 * crio uma lista de itens
	 * insiro o selecione com valor nulo
	 * e um looping para preencher com o nome a lista de itens
	 */
	@SuppressWarnings("unchecked")
	public List<SelectItem> getObjetosPaises(){
		List<Pais> paises = paisDAO.todos();
		List<SelectItem> itens = new ArrayList<SelectItem>();
		itens.add(new SelectItem(null, " -- Selecione -- "));
		for(Pais obj : paises){
			itens.add(new SelectItem(obj, obj.getNomePais()));
		}
		return itens;
	}
	
	/**
	 * @return
	 * metodo que preenche a combo de emissora
	 * crio uma lista de emissoras que recebe todas as emissoras 
	 * crio uma lista de itens
	 * insiro o selecione com valor nulo
	 * e um looping para preencher com o nome a lista de itens
	 */
	@SuppressWarnings("unchecked")
	public List<SelectItem> getObjetosEmissoras(){
		List<Emissora> emissoras = emissoraDAO.todos();
		List<SelectItem> itens = new ArrayList<SelectItem>();
		itens.add(new SelectItem(null, "-- Selecione --"));
		for(Emissora obj : emissoras){
			itens.add(new SelectItem(obj, obj.getDescricaoEmissora()));
		}
		return itens;
	}
	
	/**
	 * @return
	 * metodo que preenche a combo de interesse
	 * crio uma lista de interesses que recebe todos os interesses 
	 * crio uma lista de itens
	 * insiro o selecione com valor nulo
	 * e um looping para preencher com o nome a lista de itens
	 */
	@SuppressWarnings("unchecked")
	public List<SelectItem> getObjetosInteresses(){
		List<Interesse> interesses = interesseDAO.todos();
		List<SelectItem> itens = new ArrayList<SelectItem>();
		itens.add(new SelectItem(null, "-- Selecione --"));
		for(Interesse obj : interesses){
			itens.add(new SelectItem(obj, obj.getDescricaoInteresse()));
		}
		return itens;
	}
	
	/**
	 * metodo para carregar os estados
	 * verifico se o pais esta nulo
	 * limpo e crio uma nova lista de objetos de estado
	 * busco os estados referentes aquele pais
	 * preencho a lista de estados cde acordo com o pais selecionado
	 * caso o pais for nulo 
	 * limpo e crio uma nova lista de objetos para estado e cidade 
	 */
	public void carregarEstados(){  
		try{
			if(getPais() != null){
				iniciarEstados();
				List<Estado> estados = estadoDAO.findEstados(getPais());
				for(Estado obj : estados){
					objetosEstados.add(new SelectItem(obj.getNomeEstado()));
				}
			} else {
				iniciarEstados();
				iniciarCidades();
			}
		} catch (NullPointerException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * metodo que carrega as cidades
	 * seto o estado de acordo com o selecionado
	 * verifico se o estado esta nulo
	 * limpo e crio uma nova lista de cidades
	 * preencho a lista de cidades de acordo com o estado selecionado
	 * caso o estado for nulo
	 * limpo e crio uma nova lista de objetos para o estado e cidade
	 */
	public void carregarCidades(){
		try {
			if(!getEstado().getNomeEstado().equals("")){
				setEstado(estadoDAO.findEstado(getEstado().getNomeEstado()));
				iniciarCidades();
				List<Cidade> cidades = cidadeDAO.findCidades(getEstado());
				for(Cidade obj : cidades){
					objetosCidades.add(new SelectItem(obj.getNomeCidade()));
				}
			} else {
				iniciarEstados();
				iniciarCidades();
			}
		} catch (NullPointerException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * @return
	 * metodo que converter o objeto para string e vice-versa
	 */
	public Converter getPaisConverter(){
		PaisConverter converter = new PaisConverter();
		converter.setPaisDAO(paisDAO);
		return converter;
	}
	
	/**
	 * @return
	 * metodo que converter o objeto para string e vice-versa
	 */
	public Converter getEstadoConverter(){
		EstadoConverter converter = new EstadoConverter();
		converter.setEstadoDAO(estadoDAO);
		return converter;
	}
	
	/**
	 * @return
	 * metodo que converter o objeto para string e vice-versa
	 */
	public Converter getCidadeConverter(){
		CidadeConverter converter = new CidadeConverter();
		converter.setCidadeDAO(cidadeDAO);
		return converter;
	}
	
	/**
	 * @return
	 * metodo que converter o objeto para string e vice-versa
	 */
	public Converter getEmissoraConverter(){
		EmissoraConverter converter = new EmissoraConverter();
		converter.setEmissoraDAO(emissoraDAO);
		return converter;
	}
	
	public GrupoEnvio getGrupoEnvio() {
		return grupoEnvio;
	}

	public void setGrupoEnvio(GrupoEnvio grupoEnvio) {
		this.grupoEnvio = grupoEnvio;
	}

	public List<GrupoEnvio> getGrupos() {
		return grupos;
	}

	public void setGrupos(List<GrupoEnvio> grupos) {
		this.grupos = grupos;
	}

	public HtmlDataTable getGrupoEnvioHDT() {
		return grupoEnvioHDT;
	}

	public void setGrupoEnvioHDT(HtmlDataTable grupoEnvioHDT) {
		this.grupoEnvioHDT = grupoEnvioHDT;
	}

	public Emissora getEmissora() {
		return emissora;
	}

	public void setEmissora(Emissora emissora) {
		this.emissora = emissora;
	}

	public Serie getSerie() {
		return serie;
	}

	public void setSerie(Serie serie) {
		this.serie = serie;
	}

	public Interesse getInteresse() {
		return interesse;
	}

	public void setInteresse(Interesse interesse) {
		this.interesse = interesse;
	}

	public Pais getPais() {
		return pais;
	}

	public void setPais(Pais pais) {
		this.pais = pais;
	}

	public Estado getEstado() {
		return estado;
	}

	public void setEstado(Estado estado) {
		this.estado = estado;
	}

	public Cidade getCidade() {
		return cidade;
	}

	public void setCidade(Cidade cidade) {
		this.cidade = cidade;
	}

	public List<SelectItem> getObjetosEstados() {
		return objetosEstados;
	}

	public void setObjetosEstados(List<SelectItem> objetosEstados) {
		this.objetosEstados = objetosEstados;
	}

	public List<SelectItem> getObjetosCidades() {
		return objetosCidades;
	}

	public void setObjetosCidades(List<SelectItem> objetosCidades) {
		this.objetosCidades = objetosCidades;
	}

	public String getPesquisado() {
		return pesquisado;
	}

	public void setPesquisado(String pesquisado) {
		this.pesquisado = pesquisado;
	}

	public Contato getContato() {
		return contato;
	}

	public void setContato(Contato contato) {
		this.contato = contato;
	}

	public boolean isTodos() {
		return todos;
	}

	public void setTodos(boolean todos) {
		this.todos = todos;
	}

	public Usuario getUsuario() {
		return usuario;
	}

	public void setUsuario(Usuario usuario) {
		this.usuario = usuario;
	}

	public HtmlDataTable getUsuarioHDT() {
		return usuarioHDT;
	}

	public void setUsuarioHDT(HtmlDataTable usuarioHDT) {
		this.usuarioHDT = usuarioHDT;
	}

	public List<Usuario> getUsuarios() {
		return usuarios;
	}

	public void setUsuarios(List<Usuario> usuarios) {
		this.usuarios = usuarios;
	}

	public GrupoEnvio getVisualizar() {
		return visualizar;
	}

	public void setVisualizar(GrupoEnvio visualizar) {
		this.visualizar = visualizar;
	}

	public FiltroGrupo getFiltroGrupo() {
		return filtroGrupo;
	}

	public void setFiltroGrupo(FiltroGrupo filtroGrupo) {
		this.filtroGrupo = filtroGrupo;
	}

	public Emissora getVisualizarEmissora() {
		return visualizarEmissora;
	}

	public void setVisualizarEmissora(Emissora visualizarEmissora) {
		this.visualizarEmissora = visualizarEmissora;
	}

	public Serie getVisualizarSerie() {
		return visualizarSerie;
	}

	public void setVisualizarSerie(Serie visualizarSerie) {
		this.visualizarSerie = visualizarSerie;
	}

	public Interesse getVisualizarInteresse() {
		return visualizarInteresse;
	}

	public void setVisualizarInteresse(Interesse visualizarInteresse) {
		this.visualizarInteresse = visualizarInteresse;
	}

	public Pais getVisualizarPais() {
		return visualizarPais;
	}

	public void setVisualizarPais(Pais visualizarPais) {
		this.visualizarPais = visualizarPais;
	}

	public Estado getVisualizarEstado() {
		return visualizarEstado;
	}

	public void setVisualizarEstado(Estado visualizarEstado) {
		this.visualizarEstado = visualizarEstado;
	}

	public Cidade getVisualizarCidade() {
		return visualizarCidade;
	}

	public void setVisualizarCidade(Cidade visualizarCidade) {
		this.visualizarCidade = visualizarCidade;
	}

	public FiltroGrupo getVisualizarFiltro() {
		return visualizarFiltro;
	}

	public void setVisualizarFiltro(FiltroGrupo visualizarFiltro) {
		this.visualizarFiltro = visualizarFiltro;
	}

}
